﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Inovout.Data.Redis
{
    public abstract class RedisCommandParameter
    {

        internal static readonly byte[] CrlfButffer;
        internal static readonly byte[] ArgumentCountSymbolBuffer;
        internal static readonly byte[] ArgumentLengthSymbolBuffer;
        public static implicit operator RedisCommandParameter(string value) { return new RedisStringCommandParameter(value); }
        public static implicit operator RedisCommandParameter(long value) { return new RedisInt64CommandParameter(value); }
        public static implicit operator RedisCommandParameter(byte[] value) { return new RedisBlobCommandParameter(value); }
        static RedisCommandParameter()
        {
            ArgumentCountSymbolBuffer = Encoding.UTF8.GetBytes("*");
            ArgumentLengthSymbolBuffer = Encoding.UTF8.GetBytes("$");
            CrlfButffer = Encoding.UTF8.GetBytes(Environment.NewLine);
        }
        internal static void WriteSymbol(Stream stream, byte[] symbolBuffer, long argumentLength)
        {
            stream.Write(symbolBuffer, 0, symbolBuffer.Length);

            byte[] buffer = Encoding.UTF8.GetBytes(argumentLength.ToString());
            stream.Write(buffer, 0, buffer.Length);
            stream.Write(RedisCommandParameter.CrlfButffer, 0, RedisCommandParameter.CrlfButffer.Length);
        }

        internal abstract void Write(System.IO.Stream stream);
    }
    public abstract class RedisCommandParameter<T> : RedisCommandParameter
    {
        public T Value { get; private set; }
        public RedisCommandParameter(T value)
        {
            Value = value;
        }

        internal override void Write(Stream stream)
        {
            byte[] buffer = BuildValueBytes();
            WriteSymbol(stream, ArgumentLengthSymbolBuffer, buffer.Length);
            stream.Write(buffer, 0, buffer.Length);
            stream.Write(CrlfButffer, 0, CrlfButffer.Length);

        }
        internal abstract byte[] BuildValueBytes();
    }
}
